-
Notifications
You must be signed in to change notification settings - Fork 20
Add Certificate Authority functionality for AD #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
spoore1
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great start and as I mentioned earlier my main initial concern is around the request()/request_smartcard() methods.
My main thought here is to make request() align more closely with what you wrote for the IPA one so we can abstract it out to the GenericProvider later. I think the current request() could be made request_enrollment() and request_smartcard() renamed to request with some minor changes.
You might also consider a method to generate the INF file based on some basic input like template, subject, keysize. Then use template to select which set of configs to use for the INF based on that.
eedd166 to
bec5310
Compare
fc5e3ee to
e3824a9
Compare
danlavu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, this looks great, with a few minor nitpicks and a couple of larger requested changes.
|
@krishnavema I'm sorry, I did review this before I left for PTO but I didn't click submit review. |
e3824a9 to
cc761a8
Compare
spoore1
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another glance and it's looking very good. Just a question about the PSIni module calls you have in the request methods. I can't seem to find those.
sssd_test_framework/roles/ad.py
Outdated
| self.host.conn.run( | ||
| f""" | ||
| $iniPath = "{inf_path}" | ||
| New-PsIniFile -Path $iniPath |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't find these cmdlets on my AD server and they don't seem to be a part of PSIni from what I can tell. Maybe I'm missing something. Is this from a custom or external module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PsIni is loaded into the image, but it is a third-party module.
sssd-ci-containers/src/ansible/roles/ad/tasks/main.yml
- name: Install powershell modules
win_shell: |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Get-PackageProvider NuGet -ForceBootstrap
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
Install-Module PSIni -RequiredVersion 3.1.4 -Confirm:$False
We are using it with the GPO stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the problem with module i guess so i reverted to normal powershell script .
danlavu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, nitpicks and missing unit tests for the misc functions.
sssd_test_framework/roles/ad.py
Outdated
| self.host.conn.run( | ||
| f""" | ||
| $iniPath = "{inf_path}" | ||
| New-PsIniFile -Path $iniPath |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PsIni is loaded into the image, but it is a third-party module.
sssd-ci-containers/src/ansible/roles/ad/tasks/main.yml
- name: Install powershell modules
win_shell: |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Get-PackageProvider NuGet -ForceBootstrap
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
Install-Module PSIni -RequiredVersion 3.1.4 -Confirm:$False
We are using it with the GPO stuff.
cc761a8 to
c55f41c
Compare
danlavu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested it, but besides the single nitpick, I think this looks great. It does need to be tested; tentative approval until Scott or I can test it.
c55f41c to
01cd51d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tentative approval, will finish the approval after I test it.
spoore1
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some notes after trying to test.
- I believe the __request_enrollment() method in AD may not be necessary.
Most (if not every) smart card certificate case we'll need to cover will require an Enrollment Agent certificate because we're using Administrator to request certificates for other users. In this case, we could just create a default enrollment agent certificate for Administrator during the AD environment setup (still TBD). If we do this, we can simply have a method to get the hash for it that can be used inside of the request() method instead of passing it in to that method.
If you want to keep the code to generate the enrollment agent certificate, I would suggest making __request_enrollment() called only once during class init() or __setup() since we only need one enrollment certificate to issue other certificates.
- I think request() will be used far more than request_basic() so the latter may not be necessary either.
Since request() is what should be in the generic class, and we don't have a request_basic() for IPA, I don't think we'll need this (at least for smart card testing). If you want to keep it around for other potential usage later, I'm ok with that. It should be noted though that currently running requst_basic() even with a user name specified for the subject will return a certificate with subject = CN=Administrator. That's why we have to use the "Enroll On Behalf Of" functionality to get "CN=username" for the issued certificate's subject.
| result = self.host.conn.run( | ||
| """ | ||
| $ca = Get-ChildItem -Path Cert:\\LocalMachine\\Root ` | ||
| | Where-Object {$_.Subject -like '*CA*' -and $_.Issuer -eq $_.Subject} | Select-Object -First 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe -like '*CA*' should be -like '*CN=ad-RootCA*' to better match the CA root certificate in our test environments. In my testing, this returned a different certificate which causes a failure when verifying the certificates on the smart card.
| :rtype: tuple[str, str, str] | ||
| :raises RuntimeError: If certificate request fails. | ||
| """ | ||
| return self.__request_enrollment(template, subject, password, key_size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand why request_basic() would call __request_enrollment(). I thought the latter was just for requesting "Enrollment Agent" certificates to be used to request a smart card certificate using "Enrollment On Behalf Of" functionality since we're using Administrator to request certificates.
|
|
||
| def __request_enrollment( | ||
| self, | ||
| template: str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have template define a default value (i.e. "EnrollmentAgent2") so that it is not necessary to pass it in order to get an enrollment certificate.
| RequestType = PKCS10 | ||
| KeyUsage = 0xA0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this RequestType and KeyUsage are appropriate for normal certificate requests, I'm not 100% sure this will work for Enrollment Certificates. In my testing/research, it looked like it needed:
[NewRequest]
Subject="CN=Administrator,CN=Users,DC=ad,DC=test"
MachineKeySet=FALSE
Exportable=TRUE
RequestType=CMC
FriendlyName="Enrollment Agent"
[RequestAttributes]
CertificateTemplate="EnrollmentAgent2"
| f""" | ||
| $infContent = @" | ||
| [NewRequest] | ||
| Subject = \"{subject}\" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For an Enrollment Agent certificate, I believe the subject should be CN=Administrator,CN=Users,DC=ad,DC=test. You can probably get this data from the provider config data. I just don't know the path offhand to list here.
| [NewRequest] | ||
| Subject = \"{subject}\" | ||
| KeySpec = 1 | ||
| KeyUsage = 0xA0 | ||
| Exportable = TRUE | ||
| RequestType = CMC | ||
| RequesterName = \"{requester_name}\" | ||
| ProviderName = \"Microsoft Software Key Storage Provider\" | ||
| [RequestAttributes] | ||
| CertificateTemplate = \"{template}\" | ||
| "@ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these lines not be indented? I thought the conn.run() would handle indentation properly as long as it was indented along with the $infContent first line.
| self, | ||
| template: str, | ||
| subject: str, | ||
| enrollment_agent_cert_hash: str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that the request() method should match the one in IPA so we can make the generic method function the same way. I believe the enrollment_agent_cert_hash could be looked up inside the method (either by a lookup or by creating a new one and using that hash).
Implement certificate authority for AD